package bookTrading.seller;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

public class BookSellerAgent extends Agent {
	
	private Map<String, PriceManager> catalogue = new HashMap();
	private BookSellerGui myGui;
	
	protected void setup() {
		
		myGui = new BookSellerGuiImpl();
		myGui.setAgent(this);
		myGui.show();
		
		addBehaviour(new CallForOfferServer());
		addBehaviour(new PurchaseOrderServer());
		
		DFAgentDescription dfd = new DFAgentDescription();/**��Agent�����ķ���*/
		dfd.setName(getAID());
		ServiceDescription sd = new ServiceDescription();/**��Agent�������ϸ����*/
		sd.setType("book-selling");
		sd.setName(getLocalName() + "-book-selling");
		dfd.addServices(sd);
		try {
			DFService.register(this, dfd);
		}catch (FIPAException fe) {
			fe.printStackTrace();
                  
		}
	}
	
	protected void takeDown() {
		
		try {
			DFService.deregister(this);
		} catch (FIPAException fe) {
			fe.printStackTrace();
		}
		
		if (myGui != null) {
			myGui.dispose();
		}
		System.out.println("Seller-agent" + getAID().getName() + "is terminating.") ;
	}
	/**CyclicBehaviourѭ����Ϊ��jade.core.behaviours.CyclicBehaviour,������*/
	private class CallForOfferServer extends CyclicBehaviour {
        
	    private MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.CFP);
		
		public void action() {
            
			ACLMessage msg = myAgent.receive(mt);
			if(msg != null) {
			    String title = msg.getContent();
			    myGui.notifyUser("Received Proposal to buy "+title);
			    ACLMessage reply = msg.createReply();
			    PriceManager pm = (PriceManager) catalogue.get(title);
			    if(pm != null) {
				reply.setPerformative(ACLMessage.PROPOSE);
				reply.setContent(String.valueOf(pm.getCurrentPrice()));
			    }else {
				reply.setPerformative(ACLMessage.REFUSE);
			    }
			    myAgent.send(reply);
		    }else {
		    	block();
		    }
		    	
		}
	}
	
	private class PurchaseOrderServer extends CyclicBehaviour{
		
		MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.ACCEPT_PROPOSAL);

		public void action() {
			
			ACLMessage letter = myAgent.receive(mt);
			if(letter != null) {
				ACLMessage reply = letter.createReply();
				reply.setPerformative(ACLMessage.INFORM);
				reply.setContent("OK");
				myAgent.send(reply);
				String title = letter.getContent();
				catalogue.remove(title);
				myGui.deleteBook(title);
			}else {
				block();
			}
			
		}
		
	}
	
	private class PriceManager extends TickerBehaviour {/**TickerBehaviour����ִ��*/
		
		private String title;
		private int minPrice, currentPrice, initPrice, deltaP;
		private long initTime, deadline, deltaT;
		
		private PriceManager(Agent a, String t, int ip, int mp, Date d) {
			super(a, 60000);
			title = t;
			initPrice = ip;
			currentPrice = initPrice;
			deltaP = initPrice - mp;
			deadline = d.getTime();
			initTime = System.currentTimeMillis();
			deltaT = ((deadline - initTime) > 0 ? (deadline - initTime) : 60000);
			
		}
		public void onStart() {
			catalogue.put(title, this);
			super.onStart();
		}
		
		public void onTick() {
			
			long currentTime = System.currentTimeMillis();
			if(currentTime > deadline) {
				myGui.notifyUser("Cannot sell book: " + title);
				catalogue.remove(title);
				stop();
			}else {
				long elapsedTime = currentTime - initTime;
				currentPrice = (int)Math.round(initPrice - 1.0 * deltaP * (1.0 * elapsedTime / deltaT));
				/**����ѧϰ��ע�����Ϸ����룬��д���·�����*/
				//currentPrice = initPrice;
			}
		}
		
		public int getCurrentPrice() {
			return currentPrice;
		}
	}
	
	public void putForSale (String title, int initPrice, int minPrice, Date deadline) {
		
		addBehaviour(new PriceManager(this, title, initPrice, minPrice, deadline));
	}
	
	

}
